package com.profgj.profgj.aspect;

import com.profgj.profgj.entity.User;
import com.profgj.profgj.service.UserService;
import com.profgj.profgj.utils.UserNotifyUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 用户操作日志 和 异常捕获 切面类
 */

/**
 * 标致该类为切面类
 */
@Aspect
/**
 * 同时该类为一个组件纳入spring管理
 */
@Component
public class UserOperationLogAspect {

    /**
     * 用户通知工具服务对象
     */
    @Resource
    private UserNotifyUtils userNotifyUtils;

    /**
     * 用户服务对象
     */
    @Resource
    private UserService userService;

    /**
     * 用户操作记录日志路径
     */
    @Value("${system.userOperation}")
    private String user_operation = null;//Thread.currentThread().getContextClassLoader().getResource("").getPath() + "/static/user_operation";

    /**
     * 用户操作日志文件名
     */
    @Value("${system.userOpfilename}")
    private String fileName = null;
    /**
     * 取系统当前时间
     */
    private Date date = new Date();
    /**
     * 切入点
     * 匹配top.alanlee.template.controller包及其子包下的所有类的所有方法
     */
    @Pointcut("execution(* com.profgj.profgj.controller.*.*(..))")
    public void pointCut() {

    }


    /**
     * 取得日期时间拼接路径
     * @return
     */
    private String getDateTimePath() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 中间日期路径
        return  sdf.format(this.date) +"/";
    }
    /**
     * 创建日志输出文件对象
     * @param path
     * @return
     */
    private PrintWriter createFile(String path) {

        // 取得日期时间拼接中间路径
        String dateTimePath = getDateTimePath();
        File folder = null;
        File folder2 = null;
        File file = null;
        FileWriter fw = null;
        PrintWriter pw = null;
        try{
            folder = new File(path);
            // 不存在则创建目录
            if (!folder.exists()){
                // 创建目录
                folder.mkdirs();
            }

            // 创建文件夹2对象
            folder2 = new File(path + dateTimePath);
            if (!folder2.exists()){
                // 创建目录
                folder2.mkdirs();
            }
            file = new File(path + dateTimePath + fileName);
            if (!file.exists()){
                // 创建目录
                boolean bo = file.createNewFile();
                System.out.println("文件创建:"+bo);
            }
            // 创建文件追加输出对象
            fw = new FileWriter(file, true);
            // 支持打印写出到文件的对象
            pw = new PrintWriter(fw);
        }catch (Exception e) {
            e.printStackTrace();
        }

        return pw;
    }


    /**
     * 日志输出到文件
     */
    private void logOutPut(Integer user_id,String user_name,PrintWriter file,String optType,String methodName) {
        file.println("当前操作用户id:" + user_id + ", \t" + "当前用户名为:"+user_name + ", \t" + "执行操作:" + optType + ",\t" +
                "调用方法:" + methodName);
        file.flush();
        file.close();
    }

    /**
     * 根据具体情况进行输出  添加方法中穿插了不是管理员的情况下对用户的通知状态更变和添加了管理员通知的记录
     */
    private void selectOut(String methodName, String typeName,Integer user_id, String user_name, PrintWriter file) {

        // 如果是增加方法
        if (methodName.contains("Add")) {

            // 查询该操作不是管理员的情况下
            User user = userService.queryById(user_id);
            if (user.getRoleId() != 1) {
                // 判断添加方法名包含月能耗时更变用户通知状态和添加管理员通知
                if (methodName.contains("MonthEnergy")) {
                    // 当添加了产品月能耗记录
                    userNotifyUtils.changeUserStatus(user_id);
                }
            }

            // 添加日志输出
            logOutPut(user_id,user_name,file, typeName + "添加操作",methodName);
        }else if(methodName.contains("Change")) {
            // 修改日志输出
            logOutPut(user_id,user_name,file,typeName + "修改操作",methodName);
        } else if(methodName.contains("Delete")) {
            // 删除日志输出
            logOutPut(user_id,user_name,file,typeName + "删除操作",methodName);
        }
    }


    /**
     * 后置通知，目标方法调用前被调用
     */
    @After("pointCut()")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println("----------- 后置通知 -----------");

        // 取到方法签名
        Signature signature = joinPoint.getSignature();

        // 取得方法名
        String methodName = signature.getName();
        // 取到的方法名包含四个操作名称 并且
        if ((methodName.contains("Add") || methodName.contains("Change")|| methodName.contains("Delete")) && methodName.endsWith("Method")){

            // 获取参数数组
            Object[] args = joinPoint.getArgs();
            // 转成list
            List<Object> params = Arrays.asList(args);
            // 用户名变量存储
            String user_name = null;
            // 用户id变量存储
            Integer user_id = null;
            // 循环遍历参数
            for (Object obj : params) {
                // 判断参数是否为HttpSession类型
                if (obj instanceof HttpSession) {
                    // 强转对象
                    HttpSession session = (HttpSession) obj;
                    // 获取 用户id和用户名    user_id / user_name
                    user_id = Integer.parseInt(String.valueOf(session.getAttribute("user_id")));
                    user_name = String.valueOf(session.getAttribute("user_name"));
                }
            }

            // 获取登录的用户名和id成功的情况下
            if (user_name != null && user_id != null) {

                // 获得位置文件输出对象
                PrintWriter file = createFile(user_operation);

                // 判断是哪个类内的方法
                if (methodName.contains("MonthEnergy")) {
                    // 选择性输出
                    selectOut(methodName,"产品月能耗",user_id,user_name,file);
                } else if(methodName.contains("enterprise")) {
                    // 选择性输出
                    selectOut(methodName,"企业",user_id,user_name,file);
                } else if(methodName.contains("product")) {
                    // 选择性输出
                    selectOut(methodName,"产品",user_id,user_name,file);
                } else if(methodName.contains("projectBase")) {
                    // 选择性输出
                    selectOut(methodName,"项目基本情况",user_id,user_name,file);
                } else if(methodName.contains("cascade")) {
                    // 选择性输出
                    selectOut(methodName,"级联添加",user_id,user_name,file);
                } else if(methodName.contains("requirements")) {
                    // 选择性输出
                    selectOut(methodName,"项目要件",user_id,user_name,file);
                }else if (methodName.contains("user")){
                    // 选择性输出
                    selectOut(methodName,"用户管理",user_id,user_name,file);
                }else if (methodName.contains("PublishPolicy")){
                    // 选择性输出
                    selectOut(methodName,"政策文件",user_id,user_name,file);
                }else if (methodName.contains("task")){
                    // 选择性输出
                    selectOut(methodName,"定时短信任务",user_id,user_name,file);
                }else if (methodName.contains("unit")){
                    // 选择性输出
                    selectOut(methodName,"计量单位管理",user_id,user_name,file);
                }

            }

        }

    }

}

